﻿Imports System.Linq
Imports System.Xml.Linq
Imports System.Xml.XPath

Public Class ArmoryParser

    Private m_sRegion As String
    Private m_sRealm As String

    Public Sub New(ByVal eRegion As Enums.Region, ByVal RealmName As String)
        Select Case eRegion
            Case Enums.Region.Europe
                m_sRegion = "EU"
            Case Enums.Region.USA
                m_sRegion = "www"
            Case Else
                Throw New ApplicationException("Unknown Region : " & eRegion.ToString)
        End Select

        If RealmName.Trim <> String.Empty Then
            m_sRealm = RealmName.Trim
        Else
            Throw New ApplicationException("A Realm name is required.")
        End If
    End Sub

#Region "XML Document Fetching"
    ''' <summary>
    ''' Function to get XML data from the WOW Armory
    ''' </summary>
    ''' <param name="eXMLType">This will be used to determine which URL to use for certain xml data requests. (eXMLType = XMLType Enum)</param>
    ''' <param name="sValue">If eXMLType is Guild then Value = Guild Name, If eXMLTYPE is Character or Character_Reputation the value = Character Name (sValue = String)</param>
    ''' <returns>XElement</returns>
    ''' <remarks></remarks>
    Protected Function GetArmoryXMLData(ByVal eXMLType As Enums.XMLType, ByVal sValue As String) As XElement
        Try
            Dim xmlresource As XElement
            Dim oWebClient As New System.Net.WebClient()
            oWebClient.Headers.Add("user-agent", "MSIE 7.0")
            Select Case eXMLType
                Case Enums.XMLType.Guild
                    xmlresource = XElement.Load(New System.Xml.XmlTextReader(oWebClient.OpenRead(String.Format(WOWURL_GUILD, m_sRegion, m_sRealm, sValue))))
                Case Enums.XMLType.Character
                    xmlresource = XElement.Load(New System.Xml.XmlTextReader(oWebClient.OpenRead(String.Format(WOWURL_CHARACTER, m_sRegion, m_sRealm, sValue))))
                Case Enums.XMLType.Character_Reputation
                    xmlresource = XElement.Load(New System.Xml.XmlTextReader(oWebClient.OpenRead(String.Format(WOWURL_CHARACTERREPUTATION, m_sRegion, m_sRealm, sValue))))
                Case Else
                    Throw New ApplicationException("Unknown eXMLType : " & eXMLType.ToString)
            End Select
            Return xmlresource
        Catch wex As System.Net.WebException
            Select Case eXMLType
                Case Enums.XMLType.Guild
                    If wex.Message = "The remote server returned an error: (500) Internal Server Error." Then
                        Throw New ApplicationException("Unable to collection Guild Information, please check that you have chosen the correct Region,Realm and Guild Name.")
                    End If
            End Select
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetReputationXMLData(ByVal CharacterName As String) As Xml.XmlReader
        Dim oWebClient As New System.Net.WebClient()
        oWebClient.Headers.Add("user-agent", "MSIE 7.0")
        Dim oXMLReader As Xml.XmlReader
        Dim settings As New Xml.XmlReaderSettings
        settings.IgnoreComments = True
        settings.IgnoreWhitespace = True
        oXMLReader = Xml.XmlReader.Create(oWebClient.OpenRead(String.Format(WOWURL_CHARACTERREPUTATION, m_sRegion, m_sRealm, CharacterName)), settings)
        Return oXMLReader
    End Function

#End Region

#Region "Guild Functions"
    Public Function GetGuildInfo(ByVal GuildName As String) As Guild
        Try
            Dim oGuild As New Guild
            Dim oXMLDoc As XElement

            oXMLDoc = GetArmoryXMLData(Enums.XMLType.Guild, GuildName)

            With oGuild
                .BattleGroup = oXMLDoc.Element("guildInfo").Element("guildHeader").Attribute("battleGroup").Value
                .Faction = DirectCast(Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Attribute("faction").Value), Enums.Faction)
                .MemberCount = Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Attribute("count").Value)
                .Name = oXMLDoc.Element("guildInfo").Element("guildHeader").Attribute("name").Value
                .Realm = oXMLDoc.Element("guildInfo").Element("guildHeader").Attribute("realm").Value
                .WoWArmouryURL = oXMLDoc.Element("guildInfo").Element("guildHeader").Attribute("url").Value
                .Emblem = GetGuildEmblemInfo(oXMLDoc)
                .Members = GetGuildMembers(oXMLDoc)
            End With

            Return oGuild
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetGuildEmblemInfo(ByVal oXMLDoc As XElement) As GuildEmblem
        Try
            Dim oGuildEmblem As New GuildEmblem( _
                Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Element("emblem").Attribute("emblemBackground").Value), _
                Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Element("emblem").Attribute("emblemBorderColor").Value), _
                Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Element("emblem").Attribute("emblemBorderStyle").Value), _
                Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Element("emblem").Attribute("emblemIconColor").Value), _
                Integer.Parse(oXMLDoc.Element("guildInfo").Element("guildHeader").Element("emblem").Attribute("emblemIconStyle").Value))
            Return oGuildEmblem
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetGuildMembers(ByVal oXMLDoc As XElement) As List(Of GuildMember)
        Try
            Dim oMember As GuildMember
            Dim oGuildMembers As New List(Of GuildMember)

            Dim _ItemList = (From element In oXMLDoc.XPathSelectElements("guildInfo/guild/members/character") _
                            Select element).ToList()
            For Each oItem In _ItemList
                oMember = New GuildMember
                With oMember
                    .AchievementPoints = Integer.Parse(oItem.Attribute("achPoints").Value)
                    .CharacterClass = Integer.Parse(oItem.Attribute("classId").Value)
                    .Gender = Integer.Parse(oItem.Attribute("genderId").Value)
                    .Level = Integer.Parse(oItem.Attribute("level").Value)
                    .Name = oItem.Attribute("name").Value
                    .Race = Integer.Parse(oItem.Attribute("raceId").Value)
                    .Rank = Integer.Parse(oItem.Attribute("rank").Value)
                    .WoWArmouryURL = oItem.Attribute("url").Value
                End With
                oGuildMembers.Add(oMember)
            Next
            Return oGuildMembers
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
#End Region

#Region "Character Functions"
    Public Function GetCharacterInfo(ByVal CharacterName As String) As Character
        Try
            Dim oCharacter As New Character
            Dim oXMLDoc As XElement

            oXMLDoc = GetArmoryXMLData(Enums.XMLType.Character, CharacterName)

            'Check if there is character information in the xml results.
            Try
                If oXMLDoc.Element("characterInfo").Attribute("errCode").Value = "noCharacter" Then
                    Throw New ApplicationException("Unable to collection Character Information, please check that you have chosen the correct Region,Realm and Character Name.")
                    Exit Function
                End If
            Catch ex As Exception
                If ex.Message = "Unable to collection Character Information, please check that you have chosen the correct Region,Realm and Character Name." Then
                    Throw New ApplicationException("Unable to collection Character Information, please check that you have chosen the correct Region,Realm and Character Name.")
                End If
            End Try

            With oCharacter
                .AchievementPoints = oXMLDoc.Element("characterInfo").Element("character").Attribute("points").Value
                .ArenaCurrency = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("pvp").Element("arenacurrency").Attribute("value").Value)
                .BaseStats = GetBaseStats(oXMLDoc)
                .BattleGroup = oXMLDoc.Element("characterInfo").Element("character").Attribute("battleGroup").Value
                'ToDo Character Bars
                .CharacterBars = New CharacterBars
                .CharacterClass = Integer.Parse(oXMLDoc.Element("characterInfo").Element("character").Attribute("classId").Value)
                .CharacterModelURL = String.Format(WOWURL_CHARACTERMODEL, m_sRegion, m_sRealm, CharacterName)
                .Faction = Integer.Parse(oXMLDoc.Element("characterInfo").Element("character").Attribute("factionId").Value)
                .Gender = Integer.Parse(oXMLDoc.Element("characterInfo").Element("character").Attribute("genderId").Value)
                .Level = Integer.Parse(oXMLDoc.Element("characterInfo").Element("character").Attribute("level").Value)
                .LifeTimeHonorableKills = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("pvp").Element("lifetimehonorablekills").Attribute("value").Value)
                .Melee = GetMelee(oXMLDoc)
                .Ranged = GetRanged(oXMLDoc)
                .Name = oXMLDoc.Element("characterInfo").Element("character").Attribute("name").Value
                .Prefix = oXMLDoc.Element("characterInfo").Element("character").Attribute("prefix").Value
                .Professions = GetProfessions(oXMLDoc)
                .Race = Integer.Parse(oXMLDoc.Element("characterInfo").Element("character").Attribute("raceId").Value)
                .Resistances = GetResistances(oXMLDoc)
                .Suffix = oXMLDoc.Element("characterInfo").Element("character").Attribute("suffix").Value
                .Talants = GetTalants(oXMLDoc)
                .WoWArmouryURL = oXMLDoc.Element("characterInfo").Element("character").Attribute("charUrl").Value
                .Reputation = GetReputation(CharacterName)
                'ToDo Spell
                .Spell = New Spell
                'ToDo Defense
                .Defenses = New Defenses
            End With

            Return oCharacter
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

#Region "Base Stats"
    Protected Function GetBaseStats(ByVal oXMLDoc As XElement) As BaseStats
        Try
            Dim oBaseStats As New BaseStats
            With oBaseStats
                .Agility = GetBaseStatAgility(oXMLDoc)
                .Armour = GetBaseStatArmour(oXMLDoc)
                .Intellect = GetBaseStatIntellect(oXMLDoc)
                .Spirit = GetBaseStatSpirit(oXMLDoc)
                .Stamina = GetBaseStatStamina(oXMLDoc)
                .Strength = GetBaseStatStrength(oXMLDoc)
            End With
            Return oBaseStats
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetBaseStatAgility(ByVal oXMLDoc As XElement) As Agility
        Try
            Dim oAgility As New Agility
            With oAgility
                .Armour = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("agility").Attribute("armor").Value)
                .Attack = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("agility").Attribute("attack").Value)
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("agility").Attribute("base").Value)
                .CritHitPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("agility").Attribute("critHitPercent").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("agility").Attribute("effective").Value)
            End With
            Return oAgility
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetBaseStatArmour(ByVal oXMLDoc As XElement) As Armour
        Try
            Dim oArmour As New Armour
            With oArmour
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("armor").Attribute("base").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("armor").Attribute("effective").Value)
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("armor").Attribute("percent").Value)
                .PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("armor").Attribute("petBonus").Value)
            End With
            Return oArmour
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetBaseStatIntellect(ByVal oXMLDoc As XElement) As Intellect
        Try
            Dim oIntellect As New Intellect
            With oIntellect
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("intellect").Attribute("base").Value)
                .CritHitPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("intellect").Attribute("critHitPercent").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("intellect").Attribute("effective").Value)
                .Mana = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("intellect").Attribute("mana").Value)
                .PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("intellect").Attribute("petBonus").Value)
            End With
            Return oIntellect
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetBaseStatSpirit(ByVal oXMLDoc As XElement) As Spirit
        Try
            Dim oSpirit As New Spirit
            With oSpirit
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("spirit").Attribute("base").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("spirit").Attribute("effective").Value)
                .HealthRegen = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("spirit").Attribute("healthRegen").Value)
                .ManaRegen = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("spirit").Attribute("manaRegen").Value)
            End With
            Return oSpirit
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetBaseStatStamina(ByVal oXMLDoc As XElement) As Stamina
        Try
            Dim oStamina As New Stamina
            With oStamina
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("stamina").Attribute("base").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("stamina").Attribute("effective").Value)
                .Health = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("stamina").Attribute("health").Value)
                .PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("stamina").Attribute("petBonus").Value)
            End With
            Return oStamina
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetBaseStatStrength(ByVal oXMLDoc As XElement) As Strength
        Try
            Dim oStrength As New Strength
            With oStrength
                .Attack = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("strength").Attribute("attack").Value)
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("strength").Attribute("base").Value)
                .Block = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("strength").Attribute("block").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("baseStats").Element("strength").Attribute("effective").Value)
            End With
            Return oStrength
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
#End Region

    Protected Function GetProfessions(ByVal oXMLDoc As XElement) As List(Of Profession)
        Try
            Dim oProfession As Profession
            Dim oProfessions As New List(Of Profession)

            Dim _ItemList = (From element In oXMLDoc.XPathSelectElements("characterInfo/characterTab/professions/skill") _
                            Select element).ToList()
            For Each oItem In _ItemList
                oProfession = New Profession
                With oProfession
                    .ID = Integer.Parse(oItem.Attribute("id").Value)
                    .Key = oItem.Attribute("key").Value
                    .Max = Integer.Parse(oItem.Attribute("max").Value)
                    .Name = oItem.Attribute("name").Value
                    .Value = Integer.Parse(oItem.Attribute("value").Value)
                End With
                oProfessions.Add(oProfession)
            Next
            Return oProfessions
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetResistances(ByVal oXMLDoc As XElement) As Resistances
        Try
            Dim oResistances As New Resistances
            With oResistances
                .Arcane = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("arcane").Attribute("value").Value)
                .Arcane_PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("arcane").Attribute("petBonus").Value)
                .Fire = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("fire").Attribute("value").Value)
                .Fire_PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("fire").Attribute("petBonus").Value)
                .Frost = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("frost").Attribute("value").Value)
                .Frost_PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("frost").Attribute("petBonus").Value)
                .Holy = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("holy").Attribute("value").Value)
                .Holy_PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("holy").Attribute("petBonus").Value)
                .Nature = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("nature").Attribute("value").Value)
                .Nature_PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("nature").Attribute("petBonus").Value)
                .Shadow = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("shadow").Attribute("value").Value)
                .Shadow_PetBonus = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("resistances").Element("shadow").Attribute("petBonus").Value)
            End With
            Return oResistances
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

#Region "Melee Functions"
    Protected Function GetMelee(ByVal oXMLDoc As XElement) As Melee
        Try
            Dim oMelee As New Melee
            With oMelee
                .CritChance = GetMeleeCritChance(oXMLDoc)
                .Expertise = GetMeleeExpertise(oXMLDoc)
                .HitRating = GetMeleeHitRating(oXMLDoc)
                .MainHand = GetMeleeMainHand(oXMLDoc)
                .OffHand = GetMeleeOffHand(oXMLDoc)
                .Power = GetMeleePower(oXMLDoc)
            End With
            Return oMelee
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetMeleeCritChance(ByVal oXMLDoc As XElement) As MeleeCritChance
        Try
            Dim oMeleeCritChance As New MeleeCritChance
            With oMeleeCritChance
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("critChance").Attribute("percent").Value)
                .PlusPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("critChance").Attribute("plusPercent").Value)
                .Rating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("critChance").Attribute("rating").Value)
            End With
            Return oMeleeCritChance
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetMeleeExpertise(ByVal oXMLDoc As XElement) As MeleeExpertise
        Try
            Dim oMeleeExpertise As New MeleeExpertise
            With oMeleeExpertise
                .Additional = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("expertise").Attribute("additional").Value)
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("expertise").Attribute("percent").Value)
                .Rating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("expertise").Attribute("rating").Value)
                .Value = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("expertise").Attribute("value").Value)
            End With
            Return oMeleeExpertise
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetMeleeHitRating(ByVal oXMLDoc As XElement) As MeleeHitRating
        Try
            Dim oMeleeHitRating As New MeleeHitRating
            With oMeleeHitRating
                .IncreasedHitPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("hitRating").Attribute("increasedHitPercent").Value)
                .Penetration = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("hitRating").Attribute("penetration").Value)
                .ReducedArmorPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("hitRating").Attribute("reducedArmorPercent").Value)
                .Value = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("hitRating").Attribute("value").Value)
            End With
            Return oMeleeHitRating
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetMeleeMainHand(ByVal oXMLDoc As XElement) As MeleeMainHand
        Try
            Dim oMeleeMainHand As New MeleeMainHand
            With oMeleeMainHand
                .DPS = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandDamage").Attribute("dps").Value)
                .HastePercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandSpeed").Attribute("hastePercent").Value)
                .HasteRating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandSpeed").Attribute("hasteRating").Value)
                .Max = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandDamage").Attribute("max").Value)
                .Min = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandDamage").Attribute("min").Value)
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandDamage").Attribute("percent").Value)
                .Speed = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandDamage").Attribute("speed").Value)
                .Value = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("mainHandSpeed").Attribute("value").Value)
            End With
            Return oMeleeMainHand
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetMeleeOffHand(ByVal oXMLDoc As XElement) As MeleeOffHand
        Try
            Dim oMeleeOffHand As New MeleeOffHand
            With oMeleeOffHand
                .DPS = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandDamage").Attribute("dps").Value)
                .HastePercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandSpeed").Attribute("hastePercent").Value)
                .HasteRating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandSpeed").Attribute("hasteRating").Value)
                .Max = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandDamage").Attribute("max").Value)
                .Min = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandDamage").Attribute("min").Value)
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandDamage").Attribute("percent").Value)
                .Speed = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandDamage").Attribute("speed").Value)
                .Value = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("offHandSpeed").Attribute("value").Value)
            End With
            Return oMeleeOffHand
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
    Protected Function GetMeleePower(ByVal oXMLDoc As XElement) As MeleePower
        Try
            Dim oMeleePower As New MeleePower
            With oMeleePower
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("power").Attribute("base").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("power").Attribute("effective").Value)
                .IncreasedDps = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("melee").Element("power").Attribute("increasedDps").Value)
            End With
            Return oMeleePower
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
#End Region

#Region "Ranged Functions"
    Protected Function GetRanged(ByVal oXMLDoc As XElement) As Ranged
        Try
            Dim oRanged As New Ranged
            With oRanged
                .CritChance = GetRangedCritChance(oXMLDoc)
                .Damage = GetRangedDamage(oXMLDoc)
                .HitRating = GetRangedHitRating(oXMLDoc)
                .Power = GetRangedPower(oXMLDoc)
                .Speed = GetRangedSpeed(oXMLDoc)
                .WeaponSkill = GetRangedWeaponSkill(oXMLDoc)
            End With
            Return oRanged
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetRangedCritChance(ByVal oXMLDoc As XElement) As RangedCritChance
        Try
            Dim oRangedCritChance As New RangedCritChance
            With oRangedCritChance
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("critChance").Attribute("percent").Value)
                .PlusPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("critChance").Attribute("plusPercent").Value)
                .Rating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("critChance").Attribute("rating").Value)
            End With
            Return oRangedCritChance
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetRangedDamage(ByVal oXMLDoc As XElement) As RangedDamage
        Try
            Dim oRangedDamage As New RangedDamage
            With oRangedDamage
                .DPS = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("damage").Attribute("dps").Value)
                .Max = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("damage").Attribute("max").Value)
                .Min = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("damage").Attribute("min").Value)
                .Percent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("damage").Attribute("percent").Value)
                .Speed = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("damage").Attribute("speed").Value)
            End With
            Return oRangedDamage
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetRangedHitRating(ByVal oXMLDoc As XElement) As RangedHitRating
        Try
            Dim oRangedHitRating As New RangedHitRating
            With oRangedHitRating
                .IncreaseHitPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("hitRating").Attribute("increasedHitPercent").Value)
                .Penetration = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("hitRating").Attribute("penetration").Value)
                .ReducedArmorPercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("hitRating").Attribute("reducedArmorPercent").Value)
                .Value = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("hitRating").Attribute("value").Value)
            End With
            Return oRangedHitRating
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetRangedPower(ByVal oXMLDoc As XElement) As RangedPower
        Try
            Dim oRangedPower As New RangedPower
            With oRangedPower
                .Base = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("power").Attribute("base").Value)
                .Effective = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("power").Attribute("effective").Value)
                .IncreasedDPS = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("power").Attribute("increasedDps").Value)
                .PetAttack = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("power").Attribute("petAttack").Value)
                .PetSpell = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("power").Attribute("petSpell").Value)
            End With
            Return oRangedPower
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetRangedSpeed(ByVal oXMLDoc As XElement) As RangedSpeed
        Try
            Dim oRangedSpeed As New RangedSpeed
            With oRangedSpeed
                .HastePercent = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("speed").Attribute("hastePercent").Value)
                .HastRating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("speed").Attribute("hasteRating").Value)
                .Value = Double.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("speed").Attribute("value").Value)
            End With
            Return oRangedSpeed
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetRangedWeaponSkill(ByVal oXMLDoc As XElement) As RangedWeaponSkill
        Try
            Dim oRangedWeaponSkill As New RangedWeaponSkill
            With oRangedWeaponSkill
                .Rating = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("weaponSkill").Attribute("rating").Value)
                .Value = Integer.Parse(oXMLDoc.Element("characterInfo").Element("characterTab").Element("ranged").Element("weaponSkill").Attribute("value").Value)
            End With
            Return oRangedWeaponSkill
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function
#End Region

    Protected Function GetTalants(ByVal oXMLDoc As XElement) As List(Of TalantSpec)
        Try
            Dim oTalantSpec As TalantSpec
            Dim oTalants As New List(Of TalantSpec)

            Dim _ItemList = (From element In oXMLDoc.XPathSelectElements("characterInfo/characterTab/talentSpecs/talentSpec") _
                            Select element).ToList()
            For Each oItem In _ItemList
                oTalantSpec = New TalantSpec
                With oTalantSpec
                    Try
                        Dim i As Integer
                        i = Integer.Parse(oItem.Attribute("active").Value)
                        .Active = IIf(i = 1, True, False)
                    Catch ex As Exception
                        .Active = False
                    End Try
                    .Group = Integer.Parse(oItem.Attribute("group").Value)
                    .TalentName = oItem.Attribute("prim").Value
                    .Tree1 = Integer.Parse(oItem.Attribute("treeOne").Value)
                    .Tree2 = Integer.Parse(oItem.Attribute("treeTwo").Value)
                    .Tree3 = Integer.Parse(oItem.Attribute("treeThree").Value)
                End With
                oTalants.Add(oTalantSpec)
            Next
            Return oTalants
        Catch ex As Exception
            Throw New ApplicationException(ex.Message.ToString)
        End Try
    End Function

    Protected Function GetReputation(ByVal CharacterName As String) As List(Of Reputation)

        Dim oReputationList As New List(Of Reputation)
        Dim oReputation As Reputation

        Dim doc As Xml.XmlReader
        doc = GetReputationXMLData(CharacterName)

        Do While doc.Read
            If doc.NodeType = Xml.XmlNodeType.Element Then
                If (doc.LocalName = "faction") AndAlso (doc.GetAttribute("reputation") IsNot Nothing) Then
                    oReputation = New Reputation
                    With oReputation
                        .ID = doc.GetAttribute("id")
                        .Key = doc.GetAttribute("key")
                        .Name = doc.GetAttribute("name")
                        .Value = doc.GetAttribute("reputation")
                    End With
                    oReputationList.Add(oReputation)
                End If
            End If
        Loop
        doc.Close()

        Return oReputationList
    End Function

#End Region


End Class
